package com.shenjinzheng.dk.auth.service.impl.auth;


import com.shenjinzheng.dk.auth.dto.LoginDTO;
import com.shenjinzheng.dk.auth.entity.Auth;
import com.shenjinzheng.dk.auth.service.AuthService;
import com.shenjinzheng.dk.auth.service.UserAuthService;
import com.shenjinzheng.dk.auth.utils.JwtUtil;
import com.shenjinzheng.dk.auth.vo.UserLoginVO;
import com.shenjinzheng.dk.common.BusinessException;
import com.shenjinzheng.dk.common.enums.RespEnum;
import com.shenjinzheng.dk.user.UserInfoClient;
import com.shenjinzheng.dk.user.entity.UserInfo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author shenjinzheng
 */
@Slf4j
@Service("verificationCodeAuthService")
public class VerificationCodeAuthServiceImpl implements UserAuthService {

    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private AuthService authService;

    @Resource
    private UserInfoClient userInfoClient;

    @Override
    public void sendCode(String phone) {
        Random random = new Random();
        String code = random.nextInt(8888) + 1000 + "";
        //redis编排方式： 项目名:模块名:场景名:特征码
        //判断手机号格式
        if (phone.length() != 11) {
            throw new BusinessException(RespEnum.INVALID_PHONE);
        }
        String key = "dk:sso:login:" + phone + ":code";
        String count = "dk:sso:login:" + phone + ":count";
        //判断是否超过5次
        if (Boolean.TRUE.equals(redisTemplate.hasKey(count))) {
            String s = redisTemplate.opsForValue().get(count);
            if (s == null) {
                throw new BusinessException(RespEnum.ERROR);
            }
            if (Integer.parseInt(s) > 5) {
                throw new BusinessException(RespEnum.TOO_MANY_REQUESTS);
            }
        }

        redisTemplate.opsForValue().set(key, code, 360, TimeUnit.SECONDS);
        //记一次发送次数
        if (Boolean.FALSE.equals(redisTemplate.hasKey(count))) {
            redisTemplate.opsForValue().set(count, "1", 5, TimeUnit.MINUTES);
        } else {
            int countInt = Integer.parseInt(redisTemplate.opsForValue().get(count)) + 1;
            redisTemplate.opsForValue().set(count, countInt + "", 5, TimeUnit.MINUTES);
        }
        //往MQ中发送短信
//        rabbitTemplate.convertAndSend("test.direct", "sms", "您的登录短信验证码：" + code);
        log.info("验证码是：{}", code);
        //todo 后续补上阿里云短信服务

    }

    @Override
    public UserLoginVO login(LoginDTO loginDTO) {
        log.info("短信验证码方式登录...");
        //从数据库里拿用户信息
        Auth user = authService.lambdaQuery()
                .eq(Auth::getPhone, loginDTO.getPhone())
                .one();

        //redis取值(验证码)对比
        String key = "dk:sso:login:" + loginDTO.getPhone() + ":code";
        String codeInRedis = redisTemplate.opsForValue().get(key);
        if (codeInRedis == null) {
            throw new RuntimeException("短信验证码丢失或者失效");
        }
        if (!codeInRedis.equals(loginDTO.getCode())) {
            throw new RuntimeException("验证码错误");
        }
        //判断该用户是否存在,不存在为新用户
        if (user == null) {
            //新用户
            user = new Auth();
            user.setPhone(loginDTO.getPhone());
            user.setOpenId(loginDTO.getOpenid());
            //存入新用户
            authService.save(user);

            //存储用户基本信息
            UserInfo userInfo = new UserInfo();
            userInfo.setId(user.getUserId());
            //随机生成初始用户名
            userInfo.setUsername("用户_" + user.getUserId().substring(0, 6));
            userInfoClient.save(userInfo);
        } else {
            //不是新用户,但未绑定微信的
            user.setOpenId(loginDTO.getOpenid());
            //写入
            authService.updateById(user);
        }
        //登录成功后要删除再Redis中缓存的code,因为不需要了
        redisTemplate.delete(key);
        //获取用户信息
        UserInfo userInfo = userInfoClient.getInfoById(user.getUserId());
        //签发token
        HashMap<String, Object> map = new HashMap<>();
        map.put("id", userInfo.getId());
        if (userInfo.getIsMember().equals("0")){
            map.put("role", "user");
        }else {
            map.put("role", "member");
        }
        String token = jwtUtil.createToken(map);
        UserLoginVO userLoginVO = new UserLoginVO();
        userLoginVO.setId(user.getUserId());
        userLoginVO.setToken(token);
        return userLoginVO;
    }
}
